// NewTrainingFramework.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "../Utilities/utilities.h"
#include "Vertex.h"
#include "Shaders.h"
#include "config.h"
#include "NFG.h"
#include <conio.h>


int Init ( ESContext *esContext )
{
	glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );

#if USE_DRAW_TRIANGLE
	Vertex verticesData[3];

	verticesData[0].pos.x =  0.0f;  verticesData[0].pos.y =  0.5f;  verticesData[0].pos.z =  0.0f;
	verticesData[1].pos.x = -0.5f;  verticesData[1].pos.y = -0.5f;  verticesData[1].pos.z =  0.0f;
	verticesData[2].pos.x =  0.5f;  verticesData[2].pos.y = -0.5f;  verticesData[2].pos.z =  0.0f;

	//set color
	verticesData[0].color.x =  1.0f;  verticesData[0].color.y =  0.0f;  verticesData[0].color.z =  0.0f; verticesData[0].color.w =  1.0f;
	verticesData[1].color.x =  0.0f;  verticesData[1].color.y =  1.0f;  verticesData[1].color.z =  0.0f; verticesData[1].color.w =  1.0f;
	verticesData[2].color.x =  0.0f;  verticesData[2].color.y =  0.0f;  verticesData[2].color.z =  1.0f; verticesData[2].color.w =  1.0f;
	
	glGenBuffers(1, &vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glBufferData(GL_ARRAY_BUFFER, sizeof(verticesData), verticesData, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

#else //USE_DRAW_TRIANGLE
	//Load nfg
	CNFG* nfg = new CNFG(NFG_PATH);
	if(!nfg)
		return -1;
	numIndices = nfg->GetNumOfIndices();
	numVertex = nfg->GetNumOfVertices();


	//buffer object
	glGenBuffers(1, &vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glBufferData(GL_ARRAY_BUFFER, sizeof(VERTEX)*numVertex, nfg->GetVertiesArray(), GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);


		//-------- USE ELEMENT BUFFER OBJECT
	glGenBuffers(1, &eboId);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*numIndices, nfg->GetIndices(), GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


	// Init Texture
	int bpp;
	int width;
	int height;
	char* imageData = LoadTGA(TGA_PATH, &width, &height, &bpp);
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);
	if(bpp == 32)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
	else
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);

	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
	
#endif

	//creation of shaders and program 
	return myShaders.Init(SHADER_VS_PATH, SHADER_FS_PATH);

}

void Draw ( ESContext *esContext )
{
	glClear(GL_COLOR_BUFFER_BIT);

	glUseProgram(myShaders.program);

	glBindBuffer(GL_ARRAY_BUFFER, vboId);

		Matrix model;
	Matrix view;
	Matrix projection;
	Matrix MVP;

	Matrix tran;
	tran.SetIdentity();

#if USE_AUTO_TRANFORM
	m_pos[0] += 0.0005f;
	if(m_pos[0] > 1.0f)
		m_pos[0] = -1.0f;
#endif

	model.SetIdentity();
	tran = model.SetTranslation(m_pos[0], m_pos[1], 2.0f);

#if USE_AUTO_TRANFORM
	angleY += PI/360.0f;
	if(angleY >= PI * 2.0f)
		angleY = PI/360.0f;
#endif

	tran = tran * model.SetRotationX(angleX);
	tran = tran * model.SetRotationY(angleY);

	view.SetIdentity();
	view.SetTranslation(0.0f, 0.0f, m_pos[2]);

	projection.SetIdentity();
	projection.SetPerspective(45.0f, 4/3, 0.1f, 1000.0f);

	MVP = tran * view * projection;

	glUniformMatrix4fv(myShaders.matrixOy, 1, GL_FALSE, (GLfloat*)MVP.m);

	glEnable(GL_DEPTH_TEST);

#if USE_DRAW_TRIANGLE
	if(myShaders.positionAttribute != -1)
	{
		glEnableVertexAttribArray(myShaders.positionAttribute);
		glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	}
	if(myShaders.colorAttribute != -1)
	{
		glEnableVertexAttribArray(myShaders.colorAttribute);
		glVertexAttribPointer(myShaders.colorAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (float*)0 + 3);
	}
	
	glDrawArrays(GL_TRIANGLES, 0, 3);
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);

#else
	if(myShaders.positionAttribute != -1)
	{
		glEnableVertexAttribArray(myShaders.positionAttribute);
		glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(VERTEX), 0);
	}

	if(myShaders.textureAtt != -1)
	{
		glEnableVertexAttribArray(myShaders.textureAtt);
		glVertexAttribPointer(myShaders.textureAtt, 2, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (char*)0 + 48);
	}


	glBindTexture(GL_TEXTURE_2D, textureID); 

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId); 
	glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif //USE_DRAW_TRIANGLE

	//--------- USE ELEMENT BUFFER --------------

	glBindBuffer(GL_ARRAY_BUFFER, 0);


	eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
}

void Update ( ESContext *esContext, float deltaTime )
{

}

void Key ( ESContext *esContext, unsigned char key, bool bIsPressed)
{
	switch(key)
	{
	
	//function to translate object to left/righ/top/bottom
	case 'w':
	case 'W':
		m_pos[1] += 0.5f;
		break;
	case 's':
	case 'S':
		m_pos[1] -= 0.5f;
		break;
	case 'a':
	case 'A':
		m_pos[0] -= 0.5f;
		break;
	case 'd':
	case 'D':
		m_pos[0] += 0.5f;
		break;

	//function to change view of camera
	case 'v':
	case 'V':
		m_pos[2] += 0.5f;
		break;
	case 'z':
	case 'Z':
		m_pos[2] -= 0.5f;
		break;

	//function to rotate object around the OX/OY
	case 37:	
		angleX += PI/180.0f;
		if(angleX >= PI * 2.0f)
			angleX = PI/180.0f;
		break;
	case 38:
		angleY += PI/180.0f;
		if(angleY >= PI * 2.0f)
			angleY = PI/180.0f;
		break;
	case 39:
		angleX -= PI/180.0f;
		if(angleX <= 0.00f)
			angleX = PI * 2.0f;
		break;
	case 40:
		angleY -= PI/180.0f;
			if(angleY <= 0.00f)
				angleY = PI * 2.0f;
		
		break;


	default:
		break;
	}
}

void CleanUp()
{
	glDeleteBuffers(1, &vboId);
	glDeleteBuffers(1, &eboId);
	glDeleteBuffers(1, &textureID);
}

int _tmain(int argc, _TCHAR* argv[])
{
	ESContext esContext;

    esInitContext ( &esContext );

	esCreateWindow ( &esContext, "Hello Triangle", 960, 720, ES_WINDOW_RGB);

	if ( Init ( &esContext ) != 0 )
		return 0;

	esRegisterDrawFunc ( &esContext, Draw );
	esRegisterUpdateFunc ( &esContext, Update );
	esRegisterKeyFunc ( &esContext, Key);

	esMainLoop ( &esContext );

	//releasing OpenGL resources
	CleanUp();

	//identifying memory leaks
	MemoryDump();
	printf("Press any key...\n");
	_getch();

	return 0;
}


